home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / dialer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-27  |  9.1 KB  |  420 lines

  1. /* Automatic SLIP/PPP line dialer.
  2.  *
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  *
  5.  *    Mar '91    Bill Simpson & Glenn McGregor
  6.  *        completely re-written;
  7.  *        human readable control file;
  8.  *        includes wait for string, and speed sense;
  9.  *        dials immediately when invoked.
  10.  *    May '91 Bill Simpson
  11.  *        re-ordered command line;
  12.  *        allow dial only;
  13.  *        allow inactivity timeout without ping.
  14.  *    Sep '91 Bill Simpson
  15.  *        Check known DTR & RSLD state for redial decision
  16.  *
  17.  * Mods by PA0GRI (newsession parameters)
  18.  */
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include "global.h"
  22. #include "config.h"
  23. #include "mbuf.h"
  24. #include "timer.h"
  25. #include "proc.h"
  26. #include "iface.h"
  27. #include "netuser.h"
  28. #include "i8250.h"
  29. #include "asy.h"
  30. #include "tty.h"
  31. #include "session.h"
  32. #include "socket.h"
  33. #include "cmdparse.h"
  34. #include "devparam.h"
  35. #include "icmp.h"
  36. #include "files.h"
  37. #include "main.h"
  38. #include "trace.h"
  39.  
  40. #define MIN_INTERVAL    5L
  41.  
  42. static int redial __ARGS((struct iface *ifp,char *file));
  43.  
  44. static int dodial_control    __ARGS((int argc,char *argv[],void *p));
  45. static int dodial_send        __ARGS((int argc,char *argv[],void *p));
  46. static int dodial_speed        __ARGS((int argc,char *argv[],void *p));
  47. static int dodial_status    __ARGS((int argc,char *argv[],void *p));
  48. static int dodial_wait        __ARGS((int argc,char *argv[],void *p));
  49.  
  50.  
  51. static struct cmds dial_cmds[] = {
  52.     "control",    dodial_control,    0, 2, "control up | down",
  53.     "send",        dodial_send,    0, 2,
  54.     "send \"string\" [<milliseconds>]",
  55.     "speed",    dodial_speed,    0, 2, "speed <bps>",
  56.     "status",    dodial_status, 0, 2, "status up | down",
  57.     "wait",        dodial_wait,    0, 2,
  58.     "wait <milliseconds> [ \"string\" [speed] ]",
  59.     NULLCHAR,    NULLFP,        0, 0, "Unknown command",
  60. };
  61.  
  62.  
  63. /* dial <iface> <filename> [ <seconds> [ <pings> [<hostid>] ] ]
  64.  *    <iface>        must be asy type
  65.  *    <filename>    contains commands which are executed.
  66.  *            missing: kill outstanding dialer.
  67.  *    <seconds>    interval to check for activity on <iface>.
  68.  *    <pings>     number of missed pings before redial.
  69.  *    <hostid>    interface to ping.
  70.  */
  71. int
  72. dodialer(argc,argv,p)
  73. int argc;
  74. char *argv[];
  75. void *p;
  76. {
  77.     struct iface *ifp;
  78.     struct asy *ap;
  79.     int32 interval = 0L;        /* in seconds */
  80.     int32 last_wait = 0L;
  81.     int32 target = 0L;
  82.     int pings = 0;
  83.     int countdown;
  84.     char *filename;
  85.     char *ifn;
  86.     int result;
  87.     int s;
  88.  
  89.     if((ifp = if_lookup(argv[1])) == NULLIF){
  90.         tprintf(Badinterface,argv[1]);
  91.         return 1;
  92.     }
  93.     if( ifp->dev >= ASY_MAX || Asy[ifp->dev].iface != ifp ){
  94.         tprintf("Interface %s not asy port\n",argv[1]);
  95.         return 1;
  96.     }
  97.  
  98.     if(ifp->supv != NULLPROC){
  99.         while ( ifp->supv != NULLPROC ) {
  100.             alert(ifp->supv, EABORT);
  101.             pwait(NULL);
  102.         }
  103.         tprintf("dialer terminated on %s\n",argv[1]);
  104.     }
  105.  
  106.     if ( argc < 3 ) {
  107.         /* just terminating */
  108.         return 0;
  109.     }
  110.  
  111.     chname( Curproc, ifn = if_name( ifp, " dialer" ) );
  112.     free( ifn );
  113.     filename = rootdircat(argv[2]);
  114.  
  115.     /* handle minimal command (just thru filename) */
  116.     if ( argc < 4 ) {
  117.         /* just dialing */
  118.         result = redial(ifp, filename);
  119.  
  120.         if ( filename != argv[2] )
  121.             free(filename);
  122.         return result;
  123.  
  124.     /* get polling interval (arg 3) */
  125.     } else if ( (interval = atol(argv[3])) <= MIN_INTERVAL ) {
  126.         tprintf("interval must be > %d seconds\n", MIN_INTERVAL);
  127.         return 1;
  128.     }
  129.  
  130.     /* get the number of pings before redialing (arg 4) */
  131.     if ( argc < 5 ) {
  132.     } else if ( (pings = atoi(argv[4])) <= 0 ){
  133.         tprintf("pings must be > 0\n");
  134.         return 1;
  135.     }
  136.  
  137.     /* retrieve the host name (arg 5) */
  138.     if ( argc < 6 ) {
  139.     } else if ( (target = resolve(argv[5])) == 0L ) {
  140.         tprintf(Badhost,argv[5]);
  141.         return 1;
  142.     }
  143.  
  144.     countdown = pings;
  145.     ifp->supv = Curproc;
  146.     ap = &Asy[ ifp->dev ];
  147.  
  148.     while ( !main_exit ) {
  149.         int32 wait_for = interval;
  150.  
  151.         if ( ap->dtr_usage == FOUND_DOWN
  152.          ||  ap->dtr_usage == MOVED_DOWN
  153.          ||  ap->rlsd_line_control == MOVED_DOWN ) {
  154.             /* definitely down */
  155.             if ( redial(ifp,filename) < 0 )
  156.                 break;
  157.         } else if ( ifp->lastrecv >= last_wait ) {
  158.             /* got something recently */
  159.             wait_for -= secclock() - ifp->lastrecv;
  160.             countdown = pings;
  161.         } else if ( countdown < 1 ) {
  162.             /* we're down, or host we ping is down */
  163.             if ( redial(ifp,filename) < 0 )
  164.                 break;
  165.             countdown = pings;
  166.         } else if ( target != 0L
  167.            && (s = socket(AF_INET,SOCK_RAW,ICMP_PTCL)) != -1 ) {
  168.             pingem(s,target,0,(int16)s,0);
  169.             close_s(s);
  170.             countdown--;
  171.         } else if ( ifp->echo != NULLFP ) {
  172.             (*ifp->echo)(ifp,NULLBUF);
  173.             countdown--;
  174.         }
  175.  
  176.         last_wait = secclock();
  177.         if ( wait_for != 0L ) {
  178.             alarm( wait_for * 1000L );
  179.             if ( pwait( &(ifp->supv) ) == EABORT )
  180.                 break;
  181.             alarm(0L);        /* clear alarm */
  182.         }
  183.     }
  184.  
  185.     if ( filename != argv[2] )
  186.         free(filename);
  187.     ifp->supv = NULLPROC;    /* We're being terminated */
  188.     return 0;
  189. }
  190.  
  191.  
  192. /* execute dialer commands
  193.  * returns: -1 fatal error, 0 OK, 1 try again
  194.  */
  195. static int
  196. redial( ifp, file )
  197. struct iface *ifp;
  198. char *file;
  199. {
  200.     char *inbuf, *intmp;
  201.     FILE *fp;
  202.     int (*rawsave) __ARGS((struct iface *,struct mbuf *));
  203.     struct session *sp;
  204.     int result = 0;
  205.     int save_input = Curproc->input;
  206.     int save_output = Curproc->output;
  207.  
  208.     if((fp = fopen(file,READ_TEXT)) == NULLFILE){
  209.         tprintf("redial: can't read %s\n",file);
  210.         return -1;    /* Causes dialer proc to terminate */
  211.     }
  212.     /* Save output handler and temporarily redirect output to null */
  213.     if(ifp->raw == bitbucket){
  214.         tprintf("redial: tip or dialer already active on %s\n",ifp->name);
  215.         return -1;
  216.     }
  217.  
  218.     /* allocate a session descriptor */
  219.     if ( (sp = newsession( ifp->name, DIAL, 0 )) == NULLSESSION ) {
  220.         tputs(TooManySessions);
  221.         return 1;
  222.     }
  223.     tprintf( "Dialing on %s\n\n", ifp->name );
  224.  
  225.     /* Save output handler and temporarily redirect output to null */
  226.     rawsave = ifp->raw;
  227.     ifp->raw = bitbucket;
  228.  
  229.     /* Suspend the packet input driver. Note that the transmit driver
  230.      * is left running since we use it to send buffers to the line.
  231.      */
  232.     suspend(ifp->rxproc);
  233.  
  234. #ifdef notdef
  235. tprintf("rlsd: 0x%02x, dtr: 0x%02x\n",
  236.     Asy[ifp->dev].rlsd_line_control,
  237.     Asy[ifp->dev].dtr_usage );
  238. #endif
  239.  
  240.     inbuf = mallocw(BUFSIZ);
  241.     intmp = mallocw(BUFSIZ);
  242.     while ( fgets( inbuf, BUFSIZ, fp ) != NULLCHAR ) {
  243.         strcpy(intmp,inbuf);
  244.         rip( intmp );
  245.         log( -1, "%s dialer: %s", ifp->name, intmp );
  246.         if( (result = cmdparse(dial_cmds,inbuf,ifp)) != 0 ){
  247.             tprintf("input line: %s",intmp);
  248.             break;
  249.         }
  250.     }
  251.     free(inbuf);
  252.     free(intmp);
  253.     fclose(fp);
  254.  
  255.     if ( result == 0 ) {
  256.         ifp->lastsent = ifp->lastrecv = secclock();
  257.     }
  258.  
  259.     ifp->raw = rawsave;
  260.     resume(ifp->rxproc);
  261.     tprintf( "\nDial %s complete\n", ifp->name );
  262.  
  263.     /* Wait for awhile, so the user can read the screen,
  264.      * AND to give it time to send some packets on the new connection!
  265.      */
  266.     mspause( 10000L );
  267.     freesession( sp );
  268.     Curproc->input = save_input;
  269.     Curproc->output = save_output;
  270.     return result;
  271. }
  272.  
  273.  
  274. static int
  275. dodial_control(argc,argv,p)
  276. int argc;
  277. char *argv[];
  278. void *p;
  279. {
  280.     struct iface *ifp = p;
  281.     int param;
  282.  
  283.     if ( ifp->ioctl == NULL )
  284.         return -1;
  285.  
  286.     if ( (param = devparam( argv[1] )) == -1 )
  287.         return -1;
  288.  
  289.     (*ifp->ioctl)( ifp, param, TRUE, atol( argv[2] ) );
  290.     return 0;
  291. }
  292.  
  293.  
  294. static int
  295. dodial_send(argc,argv,p)
  296. int argc;
  297. char *argv[];
  298. void *p;
  299. {
  300.     struct iface *ifp = p;
  301.     struct mbuf *bp;
  302.  
  303.     if(argc > 2){
  304.         /* Send characters with inter-character delay
  305.          * (for dealing with prehistoric Micom switches that
  306.          * can't take back-to-back characters...yes, they
  307.          * still exist.)
  308.          */
  309.         char *cp;
  310.         int32 cdelay = atol(argv[2]);
  311.  
  312.         for(cp = argv[1];*cp != '\0';cp++){
  313.             bp = qdata(cp,1);
  314.             asy_send(ifp->dev,bp);
  315.             mspause(cdelay);
  316.         }
  317.     } else {
  318.         bp = qdata( argv[1], strlen(argv[1]) );
  319.  
  320.         if (ifp->trace & IF_TRACE_RAW)
  321.             raw_dump( ifp, IF_TRACE_OUT, bp );
  322.         asy_send( ifp->dev, bp );
  323.     }
  324.     return 0;
  325. }
  326.  
  327.  
  328. static int
  329. dodial_speed(argc,argv,p)
  330. int argc;
  331. char *argv[];
  332. void *p;
  333. {
  334.     struct iface *ifp = p;
  335.  
  336.     if ( argc < 2 ) {
  337.         tprintf( "current speed = %u bps\n", Asy[ifp->dev].speed );
  338.         return 0;
  339.     }
  340.     return asy_speed( ifp->dev, (int16)atol( argv[1] ) );
  341. }
  342.  
  343.  
  344. static int
  345. dodial_status(argc,argv,p)
  346. int argc;
  347. char *argv[];
  348. void *p;
  349. {
  350.     struct iface *ifp = p;
  351.     int param;
  352.  
  353.     if ( ifp->iostatus == NULL )
  354.         return -1;
  355.  
  356.     if ( (param = devparam( argv[1] )) == -1 )
  357.         return -1;
  358.  
  359.     (*ifp->iostatus)( ifp, param, atol( argv[2] ) );
  360.     return 0;
  361. }
  362.  
  363.  
  364. static int
  365. dodial_wait(argc,argv,p)
  366. int argc;
  367. char *argv[];
  368. void *p;
  369. {
  370.     struct iface *ifp = p;
  371.     register int c = -1;
  372.  
  373.     alarm( atol( argv[1] ) );
  374.  
  375.     if ( argc == 2 ) {
  376.         while ( (c = get_asy(ifp->dev)) != -1 ) {
  377.             tputc( c &= 0x7F );
  378.             tflush();
  379.         }
  380.         alarm( 0L );
  381.         return 0;
  382.     } else {
  383.         register char *cp = argv[2];
  384.  
  385.         while ( *cp != '\0'  &&  (c = get_asy(ifp->dev)) != -1 ) {
  386.             tputc( c &= 0x7F );
  387.             tflush();
  388.  
  389.             if (*cp++ != c) {
  390.                 cp = argv[2];
  391.             }
  392.         }
  393.  
  394.         if ( argc > 3 ) {
  395.             if ( stricmp( argv[3], "speed" ) == 0 ){
  396.                 int16 speed = 0;
  397.  
  398.                 while ( (c = get_asy(ifp->dev)) != -1 ) {
  399.                     tputc( c &= 0x7F );
  400.                     tflush();
  401.  
  402.                     if ( isdigit(c) ) {
  403.                         speed *= 10;
  404.                         speed += c - '0';
  405.                     } else {
  406.                         alarm( 0L );
  407.                         return asy_speed( ifp->dev, speed );
  408.                     }
  409.                 }
  410.             } else {
  411.                 return -1;
  412.             }
  413.         }
  414.     }
  415.     alarm( 0L );
  416.     return ( c == -1 );
  417. }
  418.  
  419.  
  420.